function PathGroup(e) {
    var z = new Array();
    var b = e;
    var h;
    var y;
    var ab;
    var E;
    var q;
    var K = 0;
    var G = 0;
    var l;
    var k;
    var Y;
    var o;
    var C;
    var v = 0;
    var r = new Array();
    var F = new Array();
    var B = 0;
    var S = 0;
    var P = 0;
    var L = 1;
    var H = 1;
    var X = this;
    var I = 0;
    var x = 1;
    var W;
    var V;
    var O = new Array();
    var d = 0;
    var aa;
    var p;
    var s;
    var w = new Array();
    var N = new Array();
    var c = new Array();
    var a = new Array();
    var J = 0;
    var g = 560;
    var j = 50;
    var Z = 0;
    var m = -1.6;
    var u = 340;
    var t;
    var M = 610;
    var T = 170;
    var A = 400;
    var R = 0;
    var U = 0;
    this.findIndexOf = function (ac, ae) {
        if (!Array.indexOf) {
            for (var ad = 0; ad < ac.length; ad++) {
                if (ac[ad] == ae) {
                    return ad;
                }
            }
            return -1;
        } else {
            return ac.indexOf(ae);
        }
    };
    this.addPath = function (ac) {
        z.push(ac);
        v++;
        if (y == null) {
            y = ac.getRect();
        } else {
            if (ac.getRect() != null) {
                y.addRectangle(ac.getRect());
            }
        }
        ab = new Distortion(y);
    };
    this.findSecondFoot = function (aj, ad) {
        var an = new Line(aj.getX());
        var al = new Array();
        al.push(aj);
        for (var af = aj.getY(); af > y.top; af -= ad) {
            var ac = af - ad;
            var ai = new Array();
            for (i in z) {
                var ag = z[i].getNodesInRow(ac, af);
                for (var ah in ag) {
                    ai.push(ag[ah]);
                }
            }
            var ak = true;
            var ae = new Array();
            for (var am = 0; am < ai.length; am++) {
                ak = false;
                for (i in ai) {
                    if (this.findIndexOf(ae, ai[i]) == -1) {
                        if (an.isNearLine(ai[i].getX(), ad) == true) {
                            an.addPoint(ai[i].getX());
                            ae.push(ai[i]);
                            ak = true;
                        }
                    }
                }
                if (ak == false) {
                    for (i in ai) {
                        if (this.findIndexOf(ae, ai[i]) == -1) {
                            return ai[i];
                        }
                    }
                }
            }
        }
        return null;
    };
    this.findFeet = function () {
        var ad = z[0].getLowestNode();
        var af = z[0];
        for (var ae = 0; ae < v; ae++) {
            var ah = z[ae].getLowestNode();
            if (ah == null) {
                var ag = 1;
            } else {
                if (ah.getY() > ad.getY()) {
                    ad = ah;
                    af = z[ae];
                }
            }
        }
        var ac = this.findSecondFoot(ad, 10);
        if (ac == null) {
            ac = this.findSecondFoot(ad, 5);
            if (ac == null) {
                ac = this.findSecondFoot(ad, 1);
                if (ac == null) {
                    return false;
                }
            }
        }
        if (ad.getX() < ac.getX()) {
            E = ad;
            q = ac;
        } else {
            q = ad;
            E = ac;
        }
        o = new Point(y.getCenterX(), y.top);
        C = new Point(y.getCenterX(), y.bottom);
        return true;
    };
    this.lockLeftFoot = function () {
        Y = E;
        l = ab.distortPointX(E.getX(), E.getY()) + K;
        k = ab.distortPointY(E.getX(), E.getY()) + G;
    };
    this.lockRightFoot = function () {
        Y = q;
        l = ab.distortPointX(q.getX(), q.getY()) + K;
        k = ab.distortPointY(q.getX(), q.getY()) + G;
    };
    this.translateLockedPos = function (ad, ac) {
        l += ad;
        k += ac;
    };
    this.draw = function () {
        if (Y != null) {
            var ad = ab.distortPointX(Y.getX(), Y.getY());
            var ac = ab.distortPointY(Y.getX(), Y.getY());
            K = l - ad;
            G = k - ac;
        }
        for (var ae = 0; ae < v; ae++) {
            z[ae].draw(ab, K, G);
        }
        for (ae = 0; ae < B; ae++) {
            var ag = ab.distortPointX(F[ae].x, F[ae].y);
            var af = ab.distortPointY(F[ae].x, F[ae].y);
            r[ae].centerOnPos(new Point((ag + K) * L + S, (af + G) * H + P));
            r[ae].draw();
        }
    };
    this.getDistortion = function () {
        return ab;
    };
    this.highlightFeet = function () {
        var ad = b.circle(E.getX(), E.getY(), 5, 5, 0).attr({ fill: '#f00', opacity: 0.5 });
        var ac = b.circle(q.getX(), q.getY(), 5, 5, 0).attr({ fill: '#0f0', opacity: 0.5 });
    };
    this.getHeadPosition = function () {
        var ac = new Point(o.x + K, o.y + G);
        return ac;
    };
    this.getFeetPosition = function () {
        var ac = new Point((C.x + K) * L + S, (C.y + G) * H + P);
        return ac;
    };
    this.getTopPos = function () {
        return (y.top + G) * H + P;
    };
    this.getCenterPos = function () {
        return new Point(y.getCenterX(), y.getCenterY());
    };
    this.getCenterPosWithOffset = function () {
        return new Point(y.getCenterX() + K, y.getCenterY() + G);
    };
    this.centerOnPos = function (ac) {
        K -= y.getCenterX() + K - ac.x;
        G -= y.getCenterY() + G - ac.y;
    };
    this.translate = function (ad, ac) {
        K += ad;
        G += ac;
    };
    this.getHeight = function () {
        return y.bottom - y.top;
    };
    this.setScale = function (ag, af, ae, ad) {
        S = ag;
        P = af;
        L = ae;
        H = ad;
        for (var ac = 0; ac < v; ac++) {
            z[ac].setScale(ag, af, ae, ad);
        }
        for (ac = 0; ac < B; ac++) {
            r[ac].setScale(ag, af, ae, ad);
        }
    };
    this.holdPathGroup = function (ac) {
        r.push(ac);
        var ad = ac.getCenterPos();
        ad.x = (ad.x - S) / L - K;
        ad.y = (ad.y - P) / H - G;
        F.push(ad);
        B++;
    };
    this.stopHoldingItem = function (ac) {
        r = new Array();
        F = new Array();
        B = 0;
    };
    this.convertGlobalPointToRelative = function (ad) {
        var ac = new Point(global.x - K, global.y - G);
        return ac;
    };
    this.makeReachLeftDistortion = function (ai, ac) {
        var af = new Point(ac.x - K, ac.y - G);
        var ag = this.findIndexOf(r, ai);
        var ah = F[ag];
        var ae = ((y.right - af.x) / (y.right - ah.x)) * ((y.bottom - ah.y) / (y.bottom - y.top));
        var ad = ((y.bottom - af.y) / (y.bottom - ah.y)) * ((y.right - ah.x) / (y.right - y.left));
        return new Point(ae, ad);
    };
    this.makeReachRightDistortion = function (ai, ac) {
        var af = new Point(ac.x - K, ac.y - G);
        var ag = this.findIndexOf(r, ai);
        var ah = F[ag];
        var ae = ((af.x - y.left) / (ah.x - y.left)) * ((y.bottom - ah.y) / (y.bottom - y.top));
        var ad = ((y.bottom - af.y) / (y.bottom - ah.y)) * ((ah.x - y.left) / (y.right - y.left));
        return new Point(ae, ad);
    };
    this.setupEggFall = function (ac) {
        V = ac;
        f(10);
    };
    var f = function (ad) {
        var ar = new Array();
        var ag = 0;
        var an = 0;
        var ae = 1000;
        var ak = 0;
        var ao = 0;
        var am = new Array();
        for (var ap = y.top + ad; ap <= y.bottom + ad; ap += ad) {
            var af = ap - ad;
            var au = new Array();
            var aq = null;
            for (var al in z) {
                var ac = z[al].getNodesInRow(af, ap);
                for (var aj in ac) {
                    au.push(ac[aj]);
                    if (aq == null) {
                        aq = new Line(au[aj].getX());
                    } else {
                        aq.addPoint(au[aj].getX());
                    }
                }
            }
            if (aq != null) {
                var ai = aq.getLength();
                if (ai >= ag) {
                    ag = ai;
                    an = ao;
                }
                if (ai < ae && ai > 0) {
                    ae = ai;
                    ak = ao;
                }
            }
            ar.push(ai);
            am.push(au);
            ao++;
        }
        var ah = ao;
        var at = an;
        for (al = an; al < ah; al++) {
            if (ar[al] <= ae + 10) {
                at = al;
                break;
            }
        }
        for (al = 0; al < at; al++) {
            nodes = am[al];
            numNodes = nodes.length;
            for (aj = 0; aj < numNodes; aj++) {
                if (X.findIndexOf(O, nodes[aj]) == -1) {
                    O.push(nodes[aj]);
                    d++;
                }
            }
        }
        W = (at + 1) * ad + G + y.top;
        aa = am;
        p = ad;
        s = at;
    };
    var D = function () {
        for (var ac = 0; ac < v; ac++) {
            z[ac].removeDeletedNodes();
        }
    };
    this.animateEgg = function (ac) {
        for (var ag = 0; ag < ac; ag++) {
            var ah = false;
            I += x;
            W += I;
            if (W > V) {
                I -= W - V;
                W = V;
                ah = true;
            }
            for (var af = 0; af < d; af++) {
                O[af].move(0, I);
            }
            rowToDelete = Math.round((W - y.top) / p);
            if (rowToDelete >= aa.length) {
                rowToDelete = aa.length - 1;
            }
            for (af = s; af <= rowToDelete; af++) {
                var ad = aa[af];
                var ae = ad.length;
                for (n = 0; n < ae; n++) {
                    ad[n].markForDelete();
                }
            }
            s = rowToDelete;
            D();
        }
        X.draw();
        return ah;
    };
    this.clearDisplay = function () {
        for (var ac = 0; ac < v; ac++) {
            z[ac].clearDisplay();
        }
        z = new Array();
        v = 0;
        y = null;
    };
    this.setupRainCloud = function (ac) {
        t = ac;
        U = Q(20);
    };
    this.animateRain = function (ak) {
        var al;
        for (var aj = 0; aj < ak; aj++) {
            if (J < j) {
                if (Math.random() > 0.75) {
                    var an = Math.random() * (y.right - y.left) + y.left + K;
                    var am = U + G - Math.random() * 60;
                    var af = Math.random() * 20 + 10;
                    var ah = ['M', an, ' ', am, 'L', an, ' ', am + af].join();
                    var ac = b.path(ah);
                    var ae = Math.random() * 8 + 5;
                    ac.attr('stroke-width', 2);
                    ac.attr('stroke', '#7bb2d6');
                    w.push(ae);
                    N.push(ac);
                    c.push(an);
                    a.push(am);
                    J++;
                }
            }
        }
        Z += ak;
        for (var ai = 0; ai < J; ai++) {
            oldX = c[ai];
            al = a[ai];
            a[ai] += w[ai] * ak;
            if (a[ai] > g) {
                c[ai] = Math.random() * (y.right - y.left) + y.left + K;
                a[ai] = U + G - Math.random() * 20;
            }
            N[ai].translate(c[ai] - oldX, a[ai] - al);
        }
        if (Z > u && g > T) {
            g += m * ak;
        }
        if (Z > A && M > g) {
            var ad = (m - Math.random() * 5) * ak;
            M += ad;
            if (R <= 0) {
                var ag = Math.random() * 10;
                R += ag;
            } else {
                if (R > 0) {
                    ag = -Math.random() * 10;
                    R += ag;
                }
            }
            t.translateLockedPos(0, ad + ag);
        }
        if (y.left + K > 100) {
            this.translate(-10 * ak, 0);
            this.draw();
        }
        if (g < U + G + 20) {
            this.translate(0, -2 * ak);
            this.draw();
        }
    };
    this.endRain = function () {
        for (var ac = 0; ac < J; ac++) {
            N[ac].remove();
        }
        N = new Array();
        J = 0;
    };
    var Q = function (ad) {
        var ar = new Array();
        var ag = 0;
        var an = 0;
        var ae = 1000;
        var ak = 0;
        var ao = 0;
        var am = new Array();
        for (var ap = y.top + ad; ap <= y.bottom + ad; ap += ad) {
            var af = ap - ad;
            var au = new Array();
            var aq = null;
            for (var al in z) {
                var ac = z[al].getNodesInRow(af, ap);
                for (var aj in ac) {
                    au.push(ac[aj]);
                    if (aq == null) {
                        aq = new Line(au[aj].getX());
                    } else {
                        aq.addPoint(au[aj].getX());
                    }
                }
            }
            if (aq != null) {
                var ai = aq.getLength();
                if (ai >= ag) {
                    ag = ai;
                    an = ao;
                }
                if (ai < ae && ai > 0) {
                    ae = ai;
                    ak = ao;
                }
            }
            ar.push(ai);
            am.push(au);
            ao++;
        }
        var ah = ao;
        var at = an;
        for (al = an; al < ah; al++) {
            if (ar[al] <= ae + 10) {
                at = al;
                break;
            }
        }
        return (at + 1) * ad + G + y.top;
    };
}
